import { useEffect, useState, useRef } from 'react';
import { userStore, Storage, RecordKeys } from '~/store';
import NetInfo from '@react-native-community/netinfo';
import { DeviceEventEmitter, AppState } from 'react-native';
import BleModule from '~/utils/ble/bleModule';
import * as cmd from '~/utils/ble/cmd.js';

let BluetoothManager = new BleModule();

export const useWebSocket = (socketURL: string) => {
    const userInfo = userStore.me;
    const [messages, setMessages] = useState<any>({});
    const [isConnected, setIsConnected] = useState(false);

    const webSocketRef = useRef<WebSocket | null>(null);
    const pingIntervalRef = useRef<NodeJS.Timeout | null>(null);
    const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
    const reconnectAttemptsRef = useRef<number>(0);
    const messageQueueRef = useRef<string[]>([]);
    const isConnectingRef = useRef<boolean>(false);
    const connectIdRef = useRef<number>(0);

    const maxReconnectAttempts = 5;

    const connectWebSocket = async () => {
        if (isConnectingRef.current) return;
        isConnectingRef.current = true;
        connectIdRef.current += 1;
        const currentConnectId = connectIdRef.current;

        console.log('📡 创建 WebSocket 实例 ID:', currentConnectId);

        clearInterval(pingIntervalRef.current!);
        clearTimeout(reconnectTimeoutRef.current!);
        pingIntervalRef.current = null;
        reconnectTimeoutRef.current = null;

        const profile = await Storage.getItem(RecordKeys.me);
        if (!profile?.user_id) {
            isConnectingRef.current = false;
            return;
        }

        const ws = new WebSocket(socketURL);
        webSocketRef.current = ws;

        ws.onopen = () => {
            if (connectIdRef.current !== currentConnectId) return;
            setIsConnected(true);
            reconnectAttemptsRef.current = 0;
            isConnectingRef.current = false;
            ws.send(JSON.stringify({
                action: 'subscribe',
                topic: `app/${userInfo.user_id}`,
            }));
            // 🔁 发送积压的消息队列
            while (messageQueueRef.current.length > 0) {
                const queuedMsg = messageQueueRef.current.shift();
                if (queuedMsg) {
                    ws.send(queuedMsg);
                }
            }
            pingIntervalRef.current = setInterval(() => {
                if (ws.readyState === WebSocket.OPEN) {
                    ws.send(JSON.stringify({ action: 'ping' }));
                    console.log('🔍 WebSocket ping sent');
                }
            }, 30000);
        };

        ws.onmessage = (e) => {
            if (connectIdRef.current !== currentConnectId) return;

            try {
                const result = JSON.parse(e.data);
                if (result.action === 'subscribe' || result.action === 'ping') return;

                let mess: any = {};
                if (typeof result.msg?.payload === 'string') {
                    try {
                        mess = JSON.parse(result.msg.payload);
                        console.log("📩 WebSocket 收到消息:", mess);
                    } catch (err) {
                        console.warn("⚠️ payload 不是 JSON 格式：", result.msg.payload);
                        return;
                    }
                }

                setMessages(mess);

                if (mess?.cmd === 'fingerClip_RT_upload') {
                    DeviceEventEmitter.emit("fingerDataListener", mess);
                }
                if (mess?.cmd === 'ble_echarts') {
                    DeviceEventEmitter.emit("BleEchartsEmitter", mess);
                }
                if (mess?.cmd === 'ble_ctrl') {
                    BluetoothManager.receiveData(cmd, mess.data, (res => { }));
                }

            } catch (error) {
                console.warn("⚠️ 消息解析失败:", error, e.data);
            }
        };

        ws.onerror = (e) => {
            if (connectIdRef.current !== currentConnectId) return;
            console.error('❌ WebSocket error:', e);
            isConnectingRef.current = false;
        };

        ws.onclose = (e) => {
            if (connectIdRef.current !== currentConnectId) return;

            console.log('⚠️ WebSocket closed:', e.code, e.reason);
            setIsConnected(false);
            clearInterval(pingIntervalRef.current!);
            pingIntervalRef.current = null;
            isConnectingRef.current = false;

            if (e.code !== 1000) {
                const attempts = reconnectAttemptsRef.current;
                if (attempts < maxReconnectAttempts) {
                    const timeout = Math.min(Math.pow(2, attempts) * 1000, 30000);
                    reconnectTimeoutRef.current = setTimeout(connectWebSocket, timeout);
                    reconnectAttemptsRef.current += 1;
                    console.log(`🔁 尝试重连 (#${attempts + 1})，将在 ${timeout / 1000}s 后`);
                } else {
                    console.error('🚫 达到最大重连次数，放弃重连');
                }
            }
        };
    };

    const sendMessage = (message: any) => {
        const msgStr = typeof message === 'string' ? message : JSON.stringify(message);

        if (webSocketRef.current?.readyState === WebSocket.OPEN) {
            webSocketRef.current.send(msgStr);
            while (messageQueueRef.current.length > 0) {
                webSocketRef.current.send(messageQueueRef.current.shift()!);
            }
        } else {
            console.warn('📭 WebSocket 未连接，消息加入队列');
            messageQueueRef.current.push(msgStr);
        }
    };

    const disConnectSocket = () => {
        if (webSocketRef.current) {
            webSocketRef.current.onopen = null;
            webSocketRef.current.onmessage = null;
            webSocketRef.current.onerror = null;
            webSocketRef.current.onclose = null;
            webSocketRef.current.close(1000, 'Client disconnected');
            webSocketRef.current = null;
        }
        clearInterval(pingIntervalRef.current!);
        clearTimeout(reconnectTimeoutRef.current!);
    };

    const shouldConnect = !!userInfo?.token;

    useEffect(() => {
        if (!shouldConnect) return;

        connectWebSocket();

        const netInfoUnsubscribe = NetInfo.addEventListener(state => {
            if (state.isConnected && !isConnected) {
                console.log('🌐 网络恢复，重新连接 WebSocket');
                connectWebSocket();
            }
        });

        const appStateSubscription = AppState.addEventListener('change', nextAppState => {
            if (nextAppState === 'active' && !isConnected) {
                console.log('📱 App 回到前台，重新连接 WebSocket');
                connectWebSocket();
            }
        });

        return () => {
            disConnectSocket();
            netInfoUnsubscribe();
            appStateSubscription.remove();
        };
    }, [shouldConnect, socketURL]);

    return { messages, isConnected, sendMessage, disConnectSocket };
};

export default useWebSocket;